#region Usings

using System;
using System.Collections.ObjectModel;
using System.Linq;
using KanbanBoard.Client.Model.Query;
using KanbanBoard.Client.ViewModel.Common;

#endregion

namespace KanbanBoard.Client.ViewModel.TaskBoardUseCase {
    public class ColumnViewModel {
        private readonly Column column;
        private readonly IContext context;

        public ColumnViewModel(Column column, IContext context) {
            this.column = column;
            this.context = context;

            Tasks = column.Tasks.OrderBy(_ => _.Priority.NumericPriority).Select(Translate).ToObservableCollection();
            DropTask = OnDropTask;
            PreviewTaskDrop = OnPreviewTaskDrop;
        }

        public string Name { get { return column.Name; } }

        public ObservableCollection<TaskViewModel> Tasks { get; private set; }
        public Action<TaskViewModel> DropTask { get; private set; }
        public Action<TaskViewModel, TaskViewModel> PreviewTaskDrop { get; private set; }

        private void OnDropTask(TaskViewModel taskViewModel) {
            context.Command.PullAsync(taskViewModel.Task.Id, column.Id);
            
            var index = Tasks.IndexOf(taskViewModel);
            if (index + 1 < Tasks.Count) {
                context.Command.PrioritizeAboveAsync(taskViewModel.Task.Id, Tasks[index + 1].Task.Id);
            } else if (index > 0) {
                context.Command.PrioritizeBelowAsync(taskViewModel.Task.Id, Tasks[index - 1].Task.Id);
            }
        }

        private void OnPreviewTaskDrop(TaskViewModel taskViewModel, TaskViewModel overTask) {
            if (taskViewModel == overTask) return;

            var newIndex = overTask != null ? Tasks.IndexOf(overTask) : Tasks.Count - 1;

            if (taskViewModel.ColumnViewModel == this && Tasks.IndexOf(taskViewModel) < newIndex && newIndex< Tasks.Count - 1) newIndex++;
            
            taskViewModel.ColumnViewModel.Tasks.Remove(taskViewModel);

            newIndex = newIndex < 0 ? 0 : newIndex;
            newIndex = newIndex > Tasks.Count ? Tasks.Count : newIndex;

            Tasks.Insert(newIndex, taskViewModel);
            taskViewModel.ColumnViewModel = this;
        }

        private TaskViewModel Translate(Task task) {
            return new TaskViewModel(task, this, context);
        }
    }
}